﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
using DotNetOpenAuth.OpenId.RelyingParty;
using Ulriksen.Umbraco.OpenId;
using umbraco.cms.businesslogic.member;
using umbraco.cms.businesslogic.property;

namespace Ulriksen.Umbraco.OpenId.Web
{
    public partial class OpenId : System.Web.UI.UserControl
    {

        private bool allowAttach;

        public bool AllowAttach
        {
            get { return allowAttach; }
            set { allowAttach = value; }
        }

        private string newUserMemberGroup;

        public string NewUserMemberGroup
        {
            get { return newUserMemberGroup; }
            set { newUserMemberGroup = value; }
        }

      
       
        protected void Page_Load(object sender, EventArgs e)
        {
            
            this.openIdBox.Focus();
            this.openIdBox.Attributes.Add("onkeydown", "if(event.which || event.keyCode){if ((event.which == 13) || (event.keyCode == 13)) {document.getElementById('" + openIdLoginButton.UniqueID.Replace("$","_") + "').click();return false;}} else {return true}; ");   


            unknownOpenidPanel.Visible = false;

           

            OpenIdRelyingParty openid = this.createRelyingParty();
            var response = openid.GetResponse();
            if (response != null)
            {
                switch (response.Status)
                {
                    case AuthenticationStatus.Authenticated:
                        // This is where you would look for any OpenID extension responses included
                        // in the authentication assertion.
                        var claimsResponse = response.GetExtension<ClaimsResponse>();
                        State.ProfileFields = claimsResponse;

                        // Store off the "friendly" username to display -- NOT for username lookup
                        State.FriendlyLoginName = response.FriendlyIdentifierForDisplay;

                        // Use FormsAuthentication to tell ASP.NET that the user is now logged in,
                        // with the OpenID Claimed Identifier as their username.
                        signupPanels.Visible = false;

                        umbraco.cms.businesslogic.member.Member member = OpenIdMember.GetMember(response.ClaimedIdentifier);
                        if (member == null)
                        {
                            DisplayCreateForm();
                            
                            loggedInOpenId.Text = response.ClaimedIdentifier;
                            Session["unknownOpenId"] = response.ClaimedIdentifier;

                            if (claimsResponse != null && !string.IsNullOrEmpty(claimsResponse.Email))
                            {
                                txtEmail.Text = claimsResponse.Email;
                                Member emailMember = Member.GetMemberFromEmail(claimsResponse.Email);
                                if (emailMember != null)
                                {
                                    panelCreateNew.Visible = false;
                                     Property openIdProperty = emailMember.getProperty("isOpenIdMember");
                                     if (openIdProperty != null && openIdProperty.Value.ToString() == "1")
                                     {
                                         errorNewAccount.Text = "E-mail is already associated with an OpenId, please login using the correct OpenId";
                                         PanelAttach.Visible = false;
                                         unknownOpenidPanel.Visible = false;
                                     }
                                     else
                                     {
                                         if (AllowAttach)
                                         {
                                             labelAttach.Text = "but your e-mail is already associated with an umbraco account, please login to attach this open id";
                                         }
                                         else
                                         {
                                             errorNewAccount.Text = "Your e-mail is already associated with an account";

                                             PanelAttach.Visible = false;
                                         }
                                     }
                                }    
                            }
                        }
                        else
                        {
                            //login
                            FormsAuthentication.RedirectFromLoginPage(member.LoginName, false);
                        }
                        
                        break;
                    case AuthenticationStatus.Canceled:
                        this.loginCanceledLabel.Visible = true;
                        break;
                    case AuthenticationStatus.Failed:
                        this.loginFailedLabel.Visible = true;
                        break;

                    // We don't need to handle SetupRequired because we're not setting
                    // IAuthenticationRequest.Mode to immediate mode.
                    ////case AuthenticationStatus.SetupRequired:
                    ////    break;
                }
            }
        }

        protected void openIdSignupButton_Click(object sender, EventArgs e)
        {

        }
        protected void openIdLoginButton_Click(object sender, EventArgs e)
        {
            //Only if the validation is ok. 
            if (!this.Page.IsValid)
                return;

            try 
            { 
                using (OpenIdRelyingParty openid = createRelyingParty())
                {
                    IAuthenticationRequest request = openid.CreateRequest(this.openIdBox.Text);

                    request.AddExtension(new ClaimsRequest {
                        Email = DemandLevel.Require,
                        FullName = DemandLevel.Request} );
                         
                    request.RedirectToProvider();

                }
            }
            catch (ProtocolException ex)
            {
                // The user probably entered an Identifier that 
                // was not a valid OpenID endpoint.
                this.openidValidator.Text = ex.Message;
                this.openidValidator.IsValid = false;
            }
            catch (WebException ex)
            {
                // The user probably entered an Identifier that 
                // was not a valid OpenID endpoint.
                this.openidValidator.Text = ex.Message;
                this.openidValidator.IsValid = false;
            }


        }
        
        protected void openidValidator_ServerValidate(object source, ServerValidateEventArgs args)
        {
            args.IsValid = Identifier.IsValid(args.Value);
        }

        private OpenIdRelyingParty createRelyingParty()
        {
            OpenIdRelyingParty openid = new OpenIdRelyingParty();
			int minsha, maxsha, minversion;
			if (int.TryParse(Request.QueryString["minsha"], out minsha)) {
				openid.SecuritySettings.MinimumHashBitLength = minsha;
			}
			if (int.TryParse(Request.QueryString["maxsha"], out maxsha)) {
				openid.SecuritySettings.MaximumHashBitLength = maxsha;
			}
			if (int.TryParse(Request.QueryString["minversion"], out minversion)) {
				switch (minversion) {
					case 1: openid.SecuritySettings.MinimumRequiredOpenIdVersion = ProtocolVersion.V10; break;
					case 2: openid.SecuritySettings.MinimumRequiredOpenIdVersion = ProtocolVersion.V20; break;
					default: throw new ArgumentOutOfRangeException("minversion");
				}
			}
			return openid;
        }

        protected void OpenIdAttach_LoggedIn(object sender, EventArgs e)
        {
            string userName = OpenIdAttach.UserName;
            Member member = Member.GetMemberByName(userName, false).FirstOrDefault();
            
            if (member != null)
                member.AttachOpenid(((DotNetOpenAuth.OpenId.UriIdentifier)Session["unknownOpenId"]));

            FormsAuthentication.RedirectFromLoginPage(member.LoginName, false);
            
        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            
            string openAuthId = ((DotNetOpenAuth.OpenId.UriIdentifier)Session["unknownOpenId"]);
            string memberName = OpenIdMember.OpenIdToUserName(openAuthId);
            
            MembershipCreateStatus membershipCreateStatus;
            Membership.CreateUser(
                memberName,
                new System.Guid().ToString(),
                this.txtEmail.Text,
                "This is an OpenID account. You must log in with your OpenID.",
                openAuthId,
                true,
                out membershipCreateStatus);

            if (membershipCreateStatus == MembershipCreateStatus.Success)
            {
                Member member = Member.GetMemberByName(memberName, false).FirstOrDefault();
                Property openIdProperty = member.getProperty("isOpenIdMember");
                openIdProperty.Value = 1;
                member.Text = State.FriendlyLoginName;


                if (!string.IsNullOrEmpty(NewUserMemberGroup))
                {
                    MemberGroup group = MemberGroup.GetByName(NewUserMemberGroup);
                    if (group != null)
                        member.AddGroup(group.Id);
                }

                member.AttachOpenid(openAuthId);
                member.Save();

                FormsAuthentication.RedirectFromLoginPage(member.LoginName, false);
            }
            else
            {
                if (membershipCreateStatus == MembershipCreateStatus.DuplicateEmail)
                {
                    
                    errorNewAccount.Text = "The e-mail is in use, please use another e-mail address or login with the existing account";
                    DisplayCreateForm();
                    labelUnknownOpenId.Visible = false;
                    loggedInOpenId.Visible = false;

                }
                else
                    errorNewAccount.Text = string.Concat("Could not createt account ", membershipCreateStatus);
            }

          
       
        }
        private void DisplayCreateForm()
        {
            unknownOpenidPanel.Visible = true;

        }
    }
    
}